{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "ef4545c0-8290-4eb1-abb1-19037d903961",
   "metadata": {},
   "source": [
    "# data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "id": "f1c03e3a-d71e-45fe-82cb-3fb4329915ad",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "AnnData object with n_obs × n_vars = 7672 × 26337\n",
      "    obs: 'n_genes'\n",
      "    var: 'gene_ids', 'feature_types', 'n_cells' 过滤后: 7672 个细胞, 26337 个基因\n",
      "AnnData object with n_obs × n_vars = 8930 × 26854\n",
      "    obs: 'n_genes'\n",
      "    var: 'gene_ids', 'feature_types', 'n_cells' 过滤后: 8930 个细胞, 26854 个基因\n",
      "AnnData object with n_obs × n_vars = 7672 × 26337\n",
      "    obs: 'n_genes'\n",
      "    var: 'gene_ids', 'feature_types', 'n_cells' 过滤后: 7672 个细胞, 26337 个基因\n",
      "AnnData object with n_obs × n_vars = 9351 × 27444\n",
      "    obs: 'n_genes'\n",
      "    var: 'gene_ids', 'feature_types', 'n_cells' 过滤后: 9351 个细胞, 27444 个基因\n",
      "AnnData object with n_obs × n_vars = 10242 × 27092\n",
      "    obs: 'n_genes'\n",
      "    var: 'gene_ids', 'feature_types', 'n_cells' 过滤后: 10242 个细胞, 27092 个基因\n",
      "AnnData object with n_obs × n_vars = 8507 × 26791\n",
      "    obs: 'n_genes'\n",
      "    var: 'gene_ids', 'feature_types', 'n_cells' 过滤后: 8507 个细胞, 26791 个基因\n",
      "AnnData object with n_obs × n_vars = 11200 × 27311\n",
      "    obs: 'n_genes'\n",
      "    var: 'gene_ids', 'feature_types', 'n_cells' 过滤后: 11200 个细胞, 27311 个基因\n",
      "AnnData object with n_obs × n_vars = 8406 × 26154\n",
      "    obs: 'n_genes'\n",
      "    var: 'gene_ids', 'feature_types', 'n_cells' 过滤后: 8406 个细胞, 26154 个基因\n",
      "AnnData object with n_obs × n_vars = 7189 × 25452\n",
      "    obs: 'n_genes'\n",
      "    var: 'gene_ids', 'feature_types', 'n_cells' 过滤后: 7189 个细胞, 25452 个基因\n",
      "AnnData object with n_obs × n_vars = 8437 × 25511\n",
      "    obs: 'n_genes'\n",
      "    var: 'gene_ids', 'feature_types', 'n_cells' 过滤后: 8437 个细胞, 25511 个基因\n",
      "AnnData object with n_obs × n_vars = 4853 × 25632\n",
      "    obs: 'n_genes'\n",
      "    var: 'gene_ids', 'feature_types', 'n_cells' 过滤后: 4853 个细胞, 25632 个基因\n",
      "AnnData object with n_obs × n_vars = 9433 × 26628\n",
      "    obs: 'n_genes'\n",
      "    var: 'gene_ids', 'feature_types', 'n_cells' 过滤后: 9433 个细胞, 26628 个基因\n",
      "AnnData object with n_obs × n_vars = 12401 × 27155\n",
      "    obs: 'n_genes'\n",
      "    var: 'gene_ids', 'feature_types', 'n_cells' 过滤后: 12401 个细胞, 27155 个基因\n"
     ]
    }
   ],
   "source": [
    "import scanpy as sc\n",
    "\n",
    "# 指定包含三个文件的目录路径\n",
    "data_dir_MACS = \"../data/geo/MACS/\"  # 替换为实际路径\n",
    "data_dir_H21 = \"../data/geo/H21/\n",
    "data_dir_H41 = \"../data/geo/H41/\"\n",
    "data_dir_H39 = \"../data/geo/H39/\"\n",
    "data_dir_H38 = \"../data/geo/H38/\"\n",
    "data_dir_H36 = \"../data/geo/H36/\"\n",
    "data_dir_H35 = \"../data/geo/H35/\"\n",
    "data_dir_H34 = \"../data/geo/H34/\"\n",
    "data_dir_H33 = \"../data/geo/H33/\"\n",
    "data_dir_H32 = \"../data/geo/H32/\"\n",
    "data_dir_H24 = \"../data/geo/H24/\"\n",
    "data_dir_H23 = \"../data/geo/H23/\"\n",
    "\n",
    "# 读取数据\n",
    "adata_MACS = sc.read_10x_mtx(data_dir_MACS, var_names=\"gene_symbols\", cache=True)\n",
    "adata_H21 = sc.read_10x_mtx(data_dir_H21, var_names=\"gene_symbols\", cache=True)\n",
    "adata_H41 = sc.read_10x_mtx(data_dir_H41, var_names=\"gene_symbols\", cache=True)\n",
    "adata_H39 = sc.read_10x_mtx(data_dir_H39, var_names=\"gene_symbols\", cache=True)\n",
    "adata_H38 = sc.read_10x_mtx(data_dir_H38, var_names=\"gene_symbols\", cache=True)\n",
    "adata_H36 = sc.read_10x_mtx(data_dir_H36, var_names=\"gene_symbols\", cache=True)\n",
    "adata_H35 = sc.read_10x_mtx(data_dir_H35, var_names=\"gene_symbols\", cache=True)\n",
    "adata_H34 = sc.read_10x_mtx(data_dir_H34, var_names=\"gene_symbols\", cache=True)\n",
    "adata_H33 = sc.read_10x_mtx(data_dir_H33, var_names=\"gene_symbols\", cache=True)\n",
    "adata_H32 = sc.read_10x_mtx(data_dir_H32, var_names=\"gene_symbols\", cache=True)\n",
    "adata_H24 = sc.read_10x_mtx(data_dir_H24, var_names=\"gene_symbols\", cache=True)\n",
    "adata_H23 = sc.read_10x_mtx(data_dir_H23, var_names=\"gene_symbols\", cache=True)\n",
    "\n",
    "adata_list = [\n",
    "    adata_MACS, adata_H21, adata_H41, adata_H39, adata_H38,\n",
    "    adata_H36, adata_H35, adata_H34, adata_H33, adata_H32,\n",
    "    adata_H24, adata_H23\n",
    "]\n",
    "\n",
    "for adata in adata_list:\n",
    "    # 过滤细胞（保留表达至少100个基因的细胞）\n",
    "    sc.pp.filter_cells(adata, min_genes=100)  # 相当于 Seurat 的 min.features=100 [1,4](@ref)\n",
    "    # 过滤基因（保留至少在3个细胞中表达的基因）\n",
    "    sc.pp.filter_genes(adata, min_cells=3)    # 相当于 Seurat 的 min.cells=3 [1,5](@ref)\n",
    "    # 可选：输出过滤后的细胞和基因数量\n",
    "    print(f\"{adata} 过滤后: {adata.n_obs} 个细胞, {adata.n_vars} 个基因\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6b01daaa-095c-42e7-8479-cd1e34a277b0",
   "metadata": {},
   "source": [
    "## filter "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "f04d8393-f721-42c7-9d1e-ce0968254db5",
   "metadata": {},
   "outputs": [],
   "source": [
    "def filter_all(adata):\n",
    "    sc.external.pp.scrublet(adata, random_state=112)  # 双细胞检测\n",
    "    adata = adata[adata.obs['predicted_doublet']==False, :].copy()\n",
    "    \n",
    "    adata=ov.pp.qc(adata,\n",
    "                  tresh={'mito_perc': 0.2, 'nUMIs': 300, 'detected_genes': 100},      # 线粒体，特征数，细胞数\n",
    "                  )\n",
    "\n",
    "    ov.utils.store_layers(adata,layers='counts')  \n",
    "\n",
    "    #归一化/高可变基因筛选\n",
    "\n",
    "    return adata"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "id": "6c171114-eeb0-448e-ae8e-e0c9cb32a6a1",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU mode activated\n",
      "Calculate QC metrics\n",
      "End calculation of QC metrics.\n",
      "Original cell number: 7599\n",
      "!!!It should be noted that the `scrublet` detection is too old and             may not work properly.!!!\n",
      "!!!if you want to use novel doublet detection,             please set `doublets_method=sccomposite`!!!\n",
      "Begin of post doublets removal and QC plot using`scrublet`\n",
      "Cells retained after scrublet: 7599, 0 removed.\n",
      "End of post doublets removal and QC plots.\n",
      "Filters application (seurat or mads)\n",
      "Lower treshold, nUMIs: 300; filtered-out-cells:         0\n",
      "Lower treshold, n genes: 100; filtered-out-cells:         2\n",
      "Lower treshold, mito %: 0.2; filtered-out-cells:         365\n",
      "Filters applicated.\n",
      "Total cell filtered out with this last --mode seurat QC (and its     chosen options): 365\n",
      "Cells retained after scrublet and seurat filtering: 7234, 365 removed.\n",
      "......The X of adata have been stored in counts\n",
      "CPU mode activated\n",
      "Calculate QC metrics\n",
      "End calculation of QC metrics.\n",
      "Original cell number: 8792\n",
      "!!!It should be noted that the `scrublet` detection is too old and             may not work properly.!!!\n",
      "!!!if you want to use novel doublet detection,             please set `doublets_method=sccomposite`!!!\n",
      "Begin of post doublets removal and QC plot using`scrublet`\n",
      "Cells retained after scrublet: 8792, 0 removed.\n",
      "End of post doublets removal and QC plots.\n",
      "Filters application (seurat or mads)\n",
      "Lower treshold, nUMIs: 300; filtered-out-cells:         0\n",
      "Lower treshold, n genes: 100; filtered-out-cells:         3\n",
      "Lower treshold, mito %: 0.2; filtered-out-cells:         549\n",
      "Filters applicated.\n",
      "Total cell filtered out with this last --mode seurat QC (and its     chosen options): 549\n",
      "Cells retained after scrublet and seurat filtering: 8243, 549 removed.\n",
      "......The X of adata have been stored in counts\n",
      "CPU mode activated\n",
      "Calculate QC metrics\n",
      "End calculation of QC metrics.\n",
      "Original cell number: 7599\n",
      "!!!It should be noted that the `scrublet` detection is too old and             may not work properly.!!!\n",
      "!!!if you want to use novel doublet detection,             please set `doublets_method=sccomposite`!!!\n",
      "Begin of post doublets removal and QC plot using`scrublet`\n",
      "Cells retained after scrublet: 7599, 0 removed.\n",
      "End of post doublets removal and QC plots.\n",
      "Filters application (seurat or mads)\n",
      "Lower treshold, nUMIs: 300; filtered-out-cells:         0\n",
      "Lower treshold, n genes: 100; filtered-out-cells:         2\n",
      "Lower treshold, mito %: 0.2; filtered-out-cells:         365\n",
      "Filters applicated.\n",
      "Total cell filtered out with this last --mode seurat QC (and its     chosen options): 365\n",
      "Cells retained after scrublet and seurat filtering: 7234, 365 removed.\n",
      "......The X of adata have been stored in counts\n",
      "CPU mode activated\n",
      "Calculate QC metrics\n",
      "End calculation of QC metrics.\n",
      "Original cell number: 9188\n",
      "!!!It should be noted that the `scrublet` detection is too old and             may not work properly.!!!\n",
      "!!!if you want to use novel doublet detection,             please set `doublets_method=sccomposite`!!!\n",
      "Begin of post doublets removal and QC plot using`scrublet`\n",
      "Cells retained after scrublet: 9187, 1 removed.\n",
      "End of post doublets removal and QC plots.\n",
      "Filters application (seurat or mads)\n",
      "Lower treshold, nUMIs: 300; filtered-out-cells:         0\n",
      "Lower treshold, n genes: 100; filtered-out-cells:         1\n",
      "Lower treshold, mito %: 0.2; filtered-out-cells:         277\n",
      "Filters applicated.\n",
      "Total cell filtered out with this last --mode seurat QC (and its     chosen options): 277\n",
      "Cells retained after scrublet and seurat filtering: 8910, 278 removed.\n",
      "......The X of adata have been stored in counts\n",
      "CPU mode activated\n",
      "Calculate QC metrics\n",
      "End calculation of QC metrics.\n",
      "Original cell number: 9928\n",
      "!!!It should be noted that the `scrublet` detection is too old and             may not work properly.!!!\n",
      "!!!if you want to use novel doublet detection,             please set `doublets_method=sccomposite`!!!\n",
      "Begin of post doublets removal and QC plot using`scrublet`\n",
      "Cells retained after scrublet: 9927, 1 removed.\n",
      "End of post doublets removal and QC plots.\n",
      "Filters application (seurat or mads)\n",
      "Lower treshold, nUMIs: 300; filtered-out-cells:         0\n",
      "Lower treshold, n genes: 100; filtered-out-cells:         1\n",
      "Lower treshold, mito %: 0.2; filtered-out-cells:         310\n",
      "Filters applicated.\n",
      "Total cell filtered out with this last --mode seurat QC (and its     chosen options): 311\n",
      "Cells retained after scrublet and seurat filtering: 9616, 312 removed.\n",
      "......The X of adata have been stored in counts\n",
      "CPU mode activated\n",
      "Calculate QC metrics\n",
      "End calculation of QC metrics.\n",
      "Original cell number: 8334\n",
      "!!!It should be noted that the `scrublet` detection is too old and             may not work properly.!!!\n",
      "!!!if you want to use novel doublet detection,             please set `doublets_method=sccomposite`!!!\n",
      "Begin of post doublets removal and QC plot using`scrublet`\n",
      "Cells retained after scrublet: 8334, 0 removed.\n",
      "End of post doublets removal and QC plots.\n",
      "Filters application (seurat or mads)\n",
      "Lower treshold, nUMIs: 300; filtered-out-cells:         0\n",
      "Lower treshold, n genes: 100; filtered-out-cells:         0\n",
      "Lower treshold, mito %: 0.2; filtered-out-cells:         277\n",
      "Filters applicated.\n",
      "Total cell filtered out with this last --mode seurat QC (and its     chosen options): 277\n",
      "Cells retained after scrublet and seurat filtering: 8057, 277 removed.\n",
      "......The X of adata have been stored in counts\n",
      "CPU mode activated\n",
      "Calculate QC metrics\n",
      "End calculation of QC metrics.\n",
      "Original cell number: 10760\n",
      "!!!It should be noted that the `scrublet` detection is too old and             may not work properly.!!!\n",
      "!!!if you want to use novel doublet detection,             please set `doublets_method=sccomposite`!!!\n",
      "Begin of post doublets removal and QC plot using`scrublet`\n",
      "Cells retained after scrublet: 10760, 0 removed.\n",
      "End of post doublets removal and QC plots.\n",
      "Filters application (seurat or mads)\n",
      "Lower treshold, nUMIs: 300; filtered-out-cells:         0\n",
      "Lower treshold, n genes: 100; filtered-out-cells:         7\n",
      "Lower treshold, mito %: 0.2; filtered-out-cells:         674\n",
      "Filters applicated.\n",
      "Total cell filtered out with this last --mode seurat QC (and its     chosen options): 674\n",
      "Cells retained after scrublet and seurat filtering: 10086, 674 removed.\n",
      "......The X of adata have been stored in counts\n",
      "CPU mode activated\n",
      "Calculate QC metrics\n",
      "End calculation of QC metrics.\n",
      "Original cell number: 8406\n",
      "!!!It should be noted that the `scrublet` detection is too old and             may not work properly.!!!\n",
      "!!!if you want to use novel doublet detection,             please set `doublets_method=sccomposite`!!!\n",
      "Begin of post doublets removal and QC plot using`scrublet`\n",
      "Cells retained after scrublet: 8266, 140 removed.\n",
      "End of post doublets removal and QC plots.\n",
      "Filters application (seurat or mads)\n",
      "Lower treshold, nUMIs: 300; filtered-out-cells:         0\n",
      "Lower treshold, n genes: 100; filtered-out-cells:         5\n",
      "Lower treshold, mito %: 0.2; filtered-out-cells:         371\n",
      "Filters applicated.\n",
      "Total cell filtered out with this last --mode seurat QC (and its     chosen options): 372\n",
      "Cells retained after scrublet and seurat filtering: 7894, 512 removed.\n",
      "......The X of adata have been stored in counts\n",
      "CPU mode activated\n",
      "Calculate QC metrics\n",
      "End calculation of QC metrics.\n",
      "Original cell number: 7184\n",
      "!!!It should be noted that the `scrublet` detection is too old and             may not work properly.!!!\n",
      "!!!if you want to use novel doublet detection,             please set `doublets_method=sccomposite`!!!\n",
      "Begin of post doublets removal and QC plot using`scrublet`\n",
      "Cells retained after scrublet: 7184, 0 removed.\n",
      "End of post doublets removal and QC plots.\n",
      "Filters application (seurat or mads)\n",
      "Lower treshold, nUMIs: 300; filtered-out-cells:         0\n",
      "Lower treshold, n genes: 100; filtered-out-cells:         1\n",
      "Lower treshold, mito %: 0.2; filtered-out-cells:         346\n",
      "Filters applicated.\n",
      "Total cell filtered out with this last --mode seurat QC (and its     chosen options): 346\n",
      "Cells retained after scrublet and seurat filtering: 6838, 346 removed.\n",
      "......The X of adata have been stored in counts\n",
      "CPU mode activated\n",
      "Calculate QC metrics\n",
      "End calculation of QC metrics.\n",
      "Original cell number: 8436\n",
      "!!!It should be noted that the `scrublet` detection is too old and             may not work properly.!!!\n",
      "!!!if you want to use novel doublet detection,             please set `doublets_method=sccomposite`!!!\n",
      "Begin of post doublets removal and QC plot using`scrublet`\n",
      "Cells retained after scrublet: 8436, 0 removed.\n",
      "End of post doublets removal and QC plots.\n",
      "Filters application (seurat or mads)\n",
      "Lower treshold, nUMIs: 300; filtered-out-cells:         0\n",
      "Lower treshold, n genes: 100; filtered-out-cells:         5\n",
      "Lower treshold, mito %: 0.2; filtered-out-cells:         341\n",
      "Filters applicated.\n",
      "Total cell filtered out with this last --mode seurat QC (and its     chosen options): 341\n",
      "Cells retained after scrublet and seurat filtering: 8095, 341 removed.\n",
      "......The X of adata have been stored in counts\n",
      "CPU mode activated\n",
      "Calculate QC metrics\n",
      "End calculation of QC metrics.\n",
      "Original cell number: 4852\n",
      "!!!It should be noted that the `scrublet` detection is too old and             may not work properly.!!!\n",
      "!!!if you want to use novel doublet detection,             please set `doublets_method=sccomposite`!!!\n",
      "Begin of post doublets removal and QC plot using`scrublet`\n",
      "Cells retained after scrublet: 4852, 0 removed.\n",
      "End of post doublets removal and QC plots.\n",
      "Filters application (seurat or mads)\n",
      "Lower treshold, nUMIs: 300; filtered-out-cells:         0\n",
      "Lower treshold, n genes: 100; filtered-out-cells:         1\n",
      "Lower treshold, mito %: 0.2; filtered-out-cells:         230\n",
      "Filters applicated.\n",
      "Total cell filtered out with this last --mode seurat QC (and its     chosen options): 230\n",
      "Cells retained after scrublet and seurat filtering: 4622, 230 removed.\n",
      "......The X of adata have been stored in counts\n",
      "CPU mode activated\n",
      "Calculate QC metrics\n",
      "End calculation of QC metrics.\n",
      "Original cell number: 9120\n",
      "!!!It should be noted that the `scrublet` detection is too old and             may not work properly.!!!\n",
      "!!!if you want to use novel doublet detection,             please set `doublets_method=sccomposite`!!!\n",
      "Begin of post doublets removal and QC plot using`scrublet`\n",
      "Cells retained after scrublet: 9118, 2 removed.\n",
      "End of post doublets removal and QC plots.\n",
      "Filters application (seurat or mads)\n",
      "Lower treshold, nUMIs: 300; filtered-out-cells:         0\n",
      "Lower treshold, n genes: 100; filtered-out-cells:         0\n",
      "Lower treshold, mito %: 0.2; filtered-out-cells:         282\n",
      "Filters applicated.\n",
      "Total cell filtered out with this last --mode seurat QC (and its     chosen options): 282\n",
      "Cells retained after scrublet and seurat filtering: 8836, 284 removed.\n",
      "......The X of adata have been stored in counts\n",
      "CPU mode activated\n",
      "Calculate QC metrics\n",
      "End calculation of QC metrics.\n",
      "Original cell number: 11981\n",
      "!!!It should be noted that the `scrublet` detection is too old and             may not work properly.!!!\n",
      "!!!if you want to use novel doublet detection,             please set `doublets_method=sccomposite`!!!\n",
      "Begin of post doublets removal and QC plot using`scrublet`\n",
      "Cells retained after scrublet: 11981, 0 removed.\n",
      "End of post doublets removal and QC plots.\n",
      "Filters application (seurat or mads)\n",
      "Lower treshold, nUMIs: 300; filtered-out-cells:         0\n",
      "Lower treshold, n genes: 100; filtered-out-cells:         2\n",
      "Lower treshold, mito %: 0.2; filtered-out-cells:         381\n",
      "Filters applicated.\n",
      "Total cell filtered out with this last --mode seurat QC (and its     chosen options): 381\n",
      "Cells retained after scrublet and seurat filtering: 11600, 381 removed.\n",
      "......The X of adata have been stored in counts\n"
     ]
    }
   ],
   "source": [
    "import omicverse as ov\n",
    "import scanpy as sc\n",
    "import scvelo as scv\n",
    "\n",
    "adata_MACS = filter_all(adata_MACS)\n",
    "adata_MACS.obs['batch']='MACS'\n",
    "adata_H21 = filter_all(adata_H21)\n",
    "adata_H21.obs['batch']='H21'\n",
    "adata_H41 = filter_all(adata_H41)\n",
    "adata_H41.obs['batch']='H41'\n",
    "adata_H39 = filter_all(adata_H39)\n",
    "adata_H39.obs['batch']='H39'\n",
    "adata_H38 = filter_all(adata_H38)\n",
    "adata_H38.obs['batch']='H38'\n",
    "adata_H36 = filter_all(adata_H36)\n",
    "adata_H36.obs['batch']='H36'\n",
    "adata_H35 = filter_all(adata_H35)\n",
    "adata_H35.obs['batch']='H35'\n",
    "adata_H34 = filter_all(adata_H34)\n",
    "adata_H34.obs['batch']='H34'\n",
    "adata_H33 = filter_all(adata_H33)\n",
    "adata_H33.obs['batch']='H33'\n",
    "adata_H32 = filter_all(adata_H32)\n",
    "adata_H32.obs['batch']='H32'\n",
    "adata_H24 = filter_all(adata_H24)\n",
    "adata_H24.obs['batch']='H24'\n",
    "adata_H23 = filter_all(adata_H23)\n",
    "adata_H23.obs['batch']='H23'"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6efb0d71-3b84-4319-a955-ac007283c71f",
   "metadata": {
    "tags": []
   },
   "source": [
    "## concat"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "id": "c3ea8628-9c47-4c1e-955f-df835178a654",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "adata_list = [\n",
    "    adata_MACS, adata_H21, adata_H41, adata_H39,\n",
    "    adata_H38, adata_H36, adata_H35, adata_H34, adata_H33,\n",
    "    adata_H32, adata_H24, adata_H23\n",
    "]\n",
    "\n",
    "merged_adata=sc.concat(adata_list, merge='same')\n",
    "merged_adata.obs['batch'].unique()\n",
    "merged_adata.var_names_make_unique()\n",
    "merged_adata.obs_names_make_unique()\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "a4d79b76-6916-439d-b037-a661d5e76d9a",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>n_genes</th>\n",
       "      <th>doublet_score</th>\n",
       "      <th>predicted_doublet</th>\n",
       "      <th>nUMIs</th>\n",
       "      <th>mito_perc</th>\n",
       "      <th>detected_genes</th>\n",
       "      <th>cell_complexity</th>\n",
       "      <th>passing_mt</th>\n",
       "      <th>passing_nUMIs</th>\n",
       "      <th>passing_ngenes</th>\n",
       "      <th>batch</th>\n",
       "      <th>sample_source</th>\n",
       "      <th>leiden_res0_25</th>\n",
       "      <th>leiden_res0_5</th>\n",
       "      <th>leiden_res1</th>\n",
       "      <th>leiden_res_5</th>\n",
       "      <th>leiden_res2</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>AAACCCAAGCCTCACG-1_H14_MACS</th>\n",
       "      <td>2757</td>\n",
       "      <td>0.047930</td>\n",
       "      <td>False</td>\n",
       "      <td>23391.0</td>\n",
       "      <td>0.007524</td>\n",
       "      <td>2757</td>\n",
       "      <td>0.117866</td>\n",
       "      <td>True</td>\n",
       "      <td>True</td>\n",
       "      <td>True</td>\n",
       "      <td>H14_MACS</td>\n",
       "      <td>unknown</td>\n",
       "      <td>6</td>\n",
       "      <td>15</td>\n",
       "      <td>26</td>\n",
       "      <td>21</td>\n",
       "      <td>41</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>AAACCCAAGCGAGTCA-1_H14_MACS</th>\n",
       "      <td>312</td>\n",
       "      <td>0.022159</td>\n",
       "      <td>False</td>\n",
       "      <td>555.0</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>312</td>\n",
       "      <td>0.562162</td>\n",
       "      <td>True</td>\n",
       "      <td>True</td>\n",
       "      <td>True</td>\n",
       "      <td>H14_MACS</td>\n",
       "      <td>unknown</td>\n",
       "      <td>11</td>\n",
       "      <td>22</td>\n",
       "      <td>28</td>\n",
       "      <td>38</td>\n",
       "      <td>38</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>AAACCCACACTTCATT-1_H14_MACS</th>\n",
       "      <td>4666</td>\n",
       "      <td>0.052754</td>\n",
       "      <td>False</td>\n",
       "      <td>77599.0</td>\n",
       "      <td>0.005799</td>\n",
       "      <td>4666</td>\n",
       "      <td>0.060130</td>\n",
       "      <td>True</td>\n",
       "      <td>True</td>\n",
       "      <td>True</td>\n",
       "      <td>H14_MACS</td>\n",
       "      <td>unknown</td>\n",
       "      <td>6</td>\n",
       "      <td>12</td>\n",
       "      <td>25</td>\n",
       "      <td>48</td>\n",
       "      <td>61</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>AAACCCAGTCTGCAAT-1_H14_MACS</th>\n",
       "      <td>2968</td>\n",
       "      <td>0.066849</td>\n",
       "      <td>False</td>\n",
       "      <td>9254.0</td>\n",
       "      <td>0.050789</td>\n",
       "      <td>2968</td>\n",
       "      <td>0.320726</td>\n",
       "      <td>True</td>\n",
       "      <td>True</td>\n",
       "      <td>True</td>\n",
       "      <td>H14_MACS</td>\n",
       "      <td>unknown</td>\n",
       "      <td>2</td>\n",
       "      <td>11</td>\n",
       "      <td>12</td>\n",
       "      <td>9</td>\n",
       "      <td>21</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>AAACCCAGTGCGGTAA-1_H14_MACS</th>\n",
       "      <td>2982</td>\n",
       "      <td>0.042339</td>\n",
       "      <td>False</td>\n",
       "      <td>7475.0</td>\n",
       "      <td>0.026756</td>\n",
       "      <td>2982</td>\n",
       "      <td>0.398930</td>\n",
       "      <td>True</td>\n",
       "      <td>True</td>\n",
       "      <td>True</td>\n",
       "      <td>H14_MACS</td>\n",
       "      <td>unknown</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>44</td>\n",
       "      <td>19</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>TTTGTTGTCAGTCTTT-1_H23</th>\n",
       "      <td>2951</td>\n",
       "      <td>0.029152</td>\n",
       "      <td>False</td>\n",
       "      <td>9706.0</td>\n",
       "      <td>0.014939</td>\n",
       "      <td>2951</td>\n",
       "      <td>0.304039</td>\n",
       "      <td>True</td>\n",
       "      <td>True</td>\n",
       "      <td>True</td>\n",
       "      <td>H23</td>\n",
       "      <td>unknown</td>\n",
       "      <td>0</td>\n",
       "      <td>2</td>\n",
       "      <td>6</td>\n",
       "      <td>2</td>\n",
       "      <td>18</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>TTTGTTGTCCGAGATT-1_H23</th>\n",
       "      <td>2795</td>\n",
       "      <td>0.014542</td>\n",
       "      <td>False</td>\n",
       "      <td>22624.0</td>\n",
       "      <td>0.012155</td>\n",
       "      <td>2795</td>\n",
       "      <td>0.123541</td>\n",
       "      <td>True</td>\n",
       "      <td>True</td>\n",
       "      <td>True</td>\n",
       "      <td>H23</td>\n",
       "      <td>unknown</td>\n",
       "      <td>15</td>\n",
       "      <td>18</td>\n",
       "      <td>30</td>\n",
       "      <td>51</td>\n",
       "      <td>60</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>TTTGTTGTCCTACGGG-1_H23</th>\n",
       "      <td>2714</td>\n",
       "      <td>0.012420</td>\n",
       "      <td>False</td>\n",
       "      <td>7253.0</td>\n",
       "      <td>0.031297</td>\n",
       "      <td>2714</td>\n",
       "      <td>0.374190</td>\n",
       "      <td>True</td>\n",
       "      <td>True</td>\n",
       "      <td>True</td>\n",
       "      <td>H23</td>\n",
       "      <td>unknown</td>\n",
       "      <td>0</td>\n",
       "      <td>2</td>\n",
       "      <td>6</td>\n",
       "      <td>2</td>\n",
       "      <td>4</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>TTTGTTGTCTGCTTTA-1_H23</th>\n",
       "      <td>4922</td>\n",
       "      <td>0.016088</td>\n",
       "      <td>False</td>\n",
       "      <td>15593.0</td>\n",
       "      <td>0.018149</td>\n",
       "      <td>4922</td>\n",
       "      <td>0.315654</td>\n",
       "      <td>True</td>\n",
       "      <td>True</td>\n",
       "      <td>True</td>\n",
       "      <td>H23</td>\n",
       "      <td>unknown</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>TTTGTTGTCTTCGTGC-1_H23</th>\n",
       "      <td>2300</td>\n",
       "      <td>0.029152</td>\n",
       "      <td>False</td>\n",
       "      <td>5553.0</td>\n",
       "      <td>0.038538</td>\n",
       "      <td>2300</td>\n",
       "      <td>0.414191</td>\n",
       "      <td>True</td>\n",
       "      <td>True</td>\n",
       "      <td>True</td>\n",
       "      <td>H23</td>\n",
       "      <td>unknown</td>\n",
       "      <td>0</td>\n",
       "      <td>2</td>\n",
       "      <td>0</td>\n",
       "      <td>4</td>\n",
       "      <td>8</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>106891 rows × 17 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "                             n_genes  doublet_score  predicted_doublet  \\\n",
       "AAACCCAAGCCTCACG-1_H14_MACS     2757       0.047930              False   \n",
       "AAACCCAAGCGAGTCA-1_H14_MACS      312       0.022159              False   \n",
       "AAACCCACACTTCATT-1_H14_MACS     4666       0.052754              False   \n",
       "AAACCCAGTCTGCAAT-1_H14_MACS     2968       0.066849              False   \n",
       "AAACCCAGTGCGGTAA-1_H14_MACS     2982       0.042339              False   \n",
       "...                              ...            ...                ...   \n",
       "TTTGTTGTCAGTCTTT-1_H23          2951       0.029152              False   \n",
       "TTTGTTGTCCGAGATT-1_H23          2795       0.014542              False   \n",
       "TTTGTTGTCCTACGGG-1_H23          2714       0.012420              False   \n",
       "TTTGTTGTCTGCTTTA-1_H23          4922       0.016088              False   \n",
       "TTTGTTGTCTTCGTGC-1_H23          2300       0.029152              False   \n",
       "\n",
       "                               nUMIs  mito_perc  detected_genes  \\\n",
       "AAACCCAAGCCTCACG-1_H14_MACS  23391.0   0.007524            2757   \n",
       "AAACCCAAGCGAGTCA-1_H14_MACS    555.0   0.000000             312   \n",
       "AAACCCACACTTCATT-1_H14_MACS  77599.0   0.005799            4666   \n",
       "AAACCCAGTCTGCAAT-1_H14_MACS   9254.0   0.050789            2968   \n",
       "AAACCCAGTGCGGTAA-1_H14_MACS   7475.0   0.026756            2982   \n",
       "...                              ...        ...             ...   \n",
       "TTTGTTGTCAGTCTTT-1_H23        9706.0   0.014939            2951   \n",
       "TTTGTTGTCCGAGATT-1_H23       22624.0   0.012155            2795   \n",
       "TTTGTTGTCCTACGGG-1_H23        7253.0   0.031297            2714   \n",
       "TTTGTTGTCTGCTTTA-1_H23       15593.0   0.018149            4922   \n",
       "TTTGTTGTCTTCGTGC-1_H23        5553.0   0.038538            2300   \n",
       "\n",
       "                             cell_complexity  passing_mt  passing_nUMIs  \\\n",
       "AAACCCAAGCCTCACG-1_H14_MACS         0.117866        True           True   \n",
       "AAACCCAAGCGAGTCA-1_H14_MACS         0.562162        True           True   \n",
       "AAACCCACACTTCATT-1_H14_MACS         0.060130        True           True   \n",
       "AAACCCAGTCTGCAAT-1_H14_MACS         0.320726        True           True   \n",
       "AAACCCAGTGCGGTAA-1_H14_MACS         0.398930        True           True   \n",
       "...                                      ...         ...            ...   \n",
       "TTTGTTGTCAGTCTTT-1_H23              0.304039        True           True   \n",
       "TTTGTTGTCCGAGATT-1_H23              0.123541        True           True   \n",
       "TTTGTTGTCCTACGGG-1_H23              0.374190        True           True   \n",
       "TTTGTTGTCTGCTTTA-1_H23              0.315654        True           True   \n",
       "TTTGTTGTCTTCGTGC-1_H23              0.414191        True           True   \n",
       "\n",
       "                             passing_ngenes     batch sample_source  \\\n",
       "AAACCCAAGCCTCACG-1_H14_MACS            True  H14_MACS       unknown   \n",
       "AAACCCAAGCGAGTCA-1_H14_MACS            True  H14_MACS       unknown   \n",
       "AAACCCACACTTCATT-1_H14_MACS            True  H14_MACS       unknown   \n",
       "AAACCCAGTCTGCAAT-1_H14_MACS            True  H14_MACS       unknown   \n",
       "AAACCCAGTGCGGTAA-1_H14_MACS            True  H14_MACS       unknown   \n",
       "...                                     ...       ...           ...   \n",
       "TTTGTTGTCAGTCTTT-1_H23                 True       H23       unknown   \n",
       "TTTGTTGTCCGAGATT-1_H23                 True       H23       unknown   \n",
       "TTTGTTGTCCTACGGG-1_H23                 True       H23       unknown   \n",
       "TTTGTTGTCTGCTTTA-1_H23                 True       H23       unknown   \n",
       "TTTGTTGTCTTCGTGC-1_H23                 True       H23       unknown   \n",
       "\n",
       "                            leiden_res0_25 leiden_res0_5 leiden_res1  \\\n",
       "AAACCCAAGCCTCACG-1_H14_MACS              6            15          26   \n",
       "AAACCCAAGCGAGTCA-1_H14_MACS             11            22          28   \n",
       "AAACCCACACTTCATT-1_H14_MACS              6            12          25   \n",
       "AAACCCAGTCTGCAAT-1_H14_MACS              2            11          12   \n",
       "AAACCCAGTGCGGTAA-1_H14_MACS              0             0           1   \n",
       "...                                    ...           ...         ...   \n",
       "TTTGTTGTCAGTCTTT-1_H23                   0             2           6   \n",
       "TTTGTTGTCCGAGATT-1_H23                  15            18          30   \n",
       "TTTGTTGTCCTACGGG-1_H23                   0             2           6   \n",
       "TTTGTTGTCTGCTTTA-1_H23                   0             0           1   \n",
       "TTTGTTGTCTTCGTGC-1_H23                   0             2           0   \n",
       "\n",
       "                            leiden_res_5 leiden_res2  \n",
       "AAACCCAAGCCTCACG-1_H14_MACS           21          41  \n",
       "AAACCCAAGCGAGTCA-1_H14_MACS           38          38  \n",
       "AAACCCACACTTCATT-1_H14_MACS           48          61  \n",
       "AAACCCAGTCTGCAAT-1_H14_MACS            9          21  \n",
       "AAACCCAGTGCGGTAA-1_H14_MACS           44          19  \n",
       "...                                  ...         ...  \n",
       "TTTGTTGTCAGTCTTT-1_H23                 2          18  \n",
       "TTTGTTGTCCGAGATT-1_H23                51          60  \n",
       "TTTGTTGTCCTACGGG-1_H23                 2           4  \n",
       "TTTGTTGTCTGCTTTA-1_H23                 0           0  \n",
       "TTTGTTGTCTTCGTGC-1_H23                 4           8  \n",
       "\n",
       "[106891 rows x 17 columns]"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "merged_adata.obs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "id": "8025365c-228a-445c-bf4f-2a9521f41f50",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "合并后细胞数: 106891, 基因数: 23078\n",
      "基因名示例:              gene_name\n",
      "AL627309.1  AL627309.1\n",
      "AL669831.5  AL669831.5\n",
      "FAM87B          FAM87B\n",
      "LINC00115    LINC00115\n",
      "FAM41C          FAM41C\n",
      "批次分布: batch\n",
      "H23         11576\n",
      "H36         10030\n",
      "H39          9588\n",
      "H41          8876\n",
      "H24          8809\n",
      "H21          8224\n",
      "H33          8081\n",
      "H38          8027\n",
      "H35          7820\n",
      "H14          7210\n",
      "H14_MACS     7210\n",
      "H34          6829\n",
      "H32          4611\n",
      "Name: count, dtype: int64\n"
     ]
    }
   ],
   "source": [
    "import pandas as pd\n",
    "\n",
    "# 待合并的 AnnData 对象列表\n",
    "adata_list = [\n",
    "    adata_MACS, adata_H21, adata_H41, adata_H39,\n",
    "    adata_H38, adata_H36, adata_H35, adata_H34, adata_H33,\n",
    "    adata_H32, adata_H24, adata_H23\n",
    "]\n",
    "\n",
    "# 1. 预处理：确保基因名唯一性并保留原始信息\n",
    "for adata in adata_list:\n",
    "    # 保留原始基因名到 var 中（若未存在）\n",
    "    if 'gene_name' not in adata.var.columns:\n",
    "        adata.var['gene_name'] = adata.var_names\n",
    "    # 确保基因名唯一（避免合并冲突）\n",
    "    adata.var_names_make_unique()\n",
    "    # 可选：添加样本来源标识到 obs\n",
    "    adata.obs['sample_source'] = adata.uns.get('sample_name', 'unknown')\n",
    "\n",
    "# 2. 合并参数配置\n",
    "batch_labels = [\"H14_MACS\", \"H21\", \"H41\", \"H39\", \"H38\", \n",
    "                \"H36\", \"H35\", \"H34\", \"H33\", \"H32\", \"H24\", \"H23\"]\n",
    "\n",
    "# 3. 执行合并（保留共同基因）\n",
    "merged_adata = sc.concat(\n",
    "    adata_list,\n",
    "    label=\"batch\",                # 存储批次信息的列名\n",
    "    keys=batch_labels,            # 每个样本的标签\n",
    "    # join=\"inner\",                 # 仅保留所有样本共有的基因（避免内存爆炸）\n",
    "    index_unique=\"_\",             # 细胞名添加批次后缀（如 AAACAT_H14）\n",
    "    merge='same'                # 处理重复的 var 列（如 gene_name）\n",
    ")\n",
    "\n",
    "# 4. 后处理：验证基因信息完整性\n",
    "# 确保 gene_name 列存在且无缺失\n",
    "\n",
    "# 5. 输出关键信息\n",
    "print(f\"合并后细胞数: {merged_adata.n_obs}, 基因数: {merged_adata.n_vars}\")\n",
    "print(\"基因名示例:\", merged_adata.var[['gene_name']].head())\n",
    "print(\"批次分布:\", merged_adata.obs['batch'].value_counts())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 80,
   "id": "9c2adaf0-5841-4909-a5f8-1d913ce733f0",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Begin robust gene identification\n",
      "After filtration, 23078/23078 genes are kept.     Among 23078 genes, 23078 genes are robust.\n",
      "End of robust gene identification.\n",
      "Begin size normalization: shiftlog and HVGs selection pearson\n",
      "Time to analyze data in cpu: 26.87827706336975 seconds.\n",
      "End of size normalization: shiftlog and HVGs selection pearson\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>gene_ids</th>\n",
       "      <th>feature_types</th>\n",
       "      <th>mt</th>\n",
       "      <th>gene_name</th>\n",
       "      <th>n_cells</th>\n",
       "      <th>percent_cells</th>\n",
       "      <th>robust</th>\n",
       "      <th>means</th>\n",
       "      <th>variances</th>\n",
       "      <th>residual_variances</th>\n",
       "      <th>highly_variable_rank</th>\n",
       "      <th>highly_variable_features</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>ISG15</th>\n",
       "      <td>ENSG00000187608</td>\n",
       "      <td>Gene Expression</td>\n",
       "      <td>False</td>\n",
       "      <td>ISG15</td>\n",
       "      <td>19335</td>\n",
       "      <td>18.088520</td>\n",
       "      <td>True</td>\n",
       "      <td>0.360021</td>\n",
       "      <td>2.482873</td>\n",
       "      <td>7.184891</td>\n",
       "      <td>1864.0</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>MXRA8</th>\n",
       "      <td>ENSG00000162576</td>\n",
       "      <td>Gene Expression</td>\n",
       "      <td>False</td>\n",
       "      <td>MXRA8</td>\n",
       "      <td>24136</td>\n",
       "      <td>22.580011</td>\n",
       "      <td>True</td>\n",
       "      <td>0.845899</td>\n",
       "      <td>5.618146</td>\n",
       "      <td>7.386443</td>\n",
       "      <td>1808.0</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>RPL22</th>\n",
       "      <td>ENSG00000116251</td>\n",
       "      <td>Gene Expression</td>\n",
       "      <td>False</td>\n",
       "      <td>RPL22</td>\n",
       "      <td>88116</td>\n",
       "      <td>82.435378</td>\n",
       "      <td>True</td>\n",
       "      <td>14.673621</td>\n",
       "      <td>568.010409</td>\n",
       "      <td>8.778378</td>\n",
       "      <td>1461.0</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>ERRFI1</th>\n",
       "      <td>ENSG00000116285</td>\n",
       "      <td>Gene Expression</td>\n",
       "      <td>False</td>\n",
       "      <td>ERRFI1</td>\n",
       "      <td>25696</td>\n",
       "      <td>24.039442</td>\n",
       "      <td>True</td>\n",
       "      <td>1.665201</td>\n",
       "      <td>41.690070</td>\n",
       "      <td>24.395156</td>\n",
       "      <td>337.0</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>AL034417.2</th>\n",
       "      <td>ENSG00000238290</td>\n",
       "      <td>Gene Expression</td>\n",
       "      <td>False</td>\n",
       "      <td>AL034417.2</td>\n",
       "      <td>6653</td>\n",
       "      <td>6.224097</td>\n",
       "      <td>True</td>\n",
       "      <td>0.152080</td>\n",
       "      <td>0.776722</td>\n",
       "      <td>6.924184</td>\n",
       "      <td>1950.0</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>MT-ND4</th>\n",
       "      <td>ENSG00000198886</td>\n",
       "      <td>Gene Expression</td>\n",
       "      <td>True</td>\n",
       "      <td>MT-ND4</td>\n",
       "      <td>99645</td>\n",
       "      <td>93.221132</td>\n",
       "      <td>True</td>\n",
       "      <td>33.715851</td>\n",
       "      <td>2111.944134</td>\n",
       "      <td>17.854710</td>\n",
       "      <td>550.0</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>MT-ND5</th>\n",
       "      <td>ENSG00000198786</td>\n",
       "      <td>Gene Expression</td>\n",
       "      <td>True</td>\n",
       "      <td>MT-ND5</td>\n",
       "      <td>91074</td>\n",
       "      <td>85.202683</td>\n",
       "      <td>True</td>\n",
       "      <td>11.625198</td>\n",
       "      <td>221.280413</td>\n",
       "      <td>9.081979</td>\n",
       "      <td>1391.0</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>MT-CYB</th>\n",
       "      <td>ENSG00000198727</td>\n",
       "      <td>Gene Expression</td>\n",
       "      <td>True</td>\n",
       "      <td>MT-CYB</td>\n",
       "      <td>99488</td>\n",
       "      <td>93.074253</td>\n",
       "      <td>True</td>\n",
       "      <td>42.056955</td>\n",
       "      <td>2675.267801</td>\n",
       "      <td>20.634519</td>\n",
       "      <td>425.0</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>AC233755.2</th>\n",
       "      <td>ENSG00000277856</td>\n",
       "      <td>Gene Expression</td>\n",
       "      <td>False</td>\n",
       "      <td>AC233755.2</td>\n",
       "      <td>538</td>\n",
       "      <td>0.503316</td>\n",
       "      <td>True</td>\n",
       "      <td>0.153474</td>\n",
       "      <td>59.818648</td>\n",
       "      <td>28.106683</td>\n",
       "      <td>274.0</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>AC233755.1</th>\n",
       "      <td>ENSG00000275063</td>\n",
       "      <td>Gene Expression</td>\n",
       "      <td>False</td>\n",
       "      <td>AC233755.1</td>\n",
       "      <td>1442</td>\n",
       "      <td>1.349038</td>\n",
       "      <td>True</td>\n",
       "      <td>0.148759</td>\n",
       "      <td>12.703186</td>\n",
       "      <td>18.970033</td>\n",
       "      <td>497.0</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>2000 rows × 12 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "                   gene_ids    feature_types     mt   gene_name  n_cells  \\\n",
       "ISG15       ENSG00000187608  Gene Expression  False       ISG15    19335   \n",
       "MXRA8       ENSG00000162576  Gene Expression  False       MXRA8    24136   \n",
       "RPL22       ENSG00000116251  Gene Expression  False       RPL22    88116   \n",
       "ERRFI1      ENSG00000116285  Gene Expression  False      ERRFI1    25696   \n",
       "AL034417.2  ENSG00000238290  Gene Expression  False  AL034417.2     6653   \n",
       "...                     ...              ...    ...         ...      ...   \n",
       "MT-ND4      ENSG00000198886  Gene Expression   True      MT-ND4    99645   \n",
       "MT-ND5      ENSG00000198786  Gene Expression   True      MT-ND5    91074   \n",
       "MT-CYB      ENSG00000198727  Gene Expression   True      MT-CYB    99488   \n",
       "AC233755.2  ENSG00000277856  Gene Expression  False  AC233755.2      538   \n",
       "AC233755.1  ENSG00000275063  Gene Expression  False  AC233755.1     1442   \n",
       "\n",
       "            percent_cells  robust      means    variances  residual_variances  \\\n",
       "ISG15           18.088520    True   0.360021     2.482873            7.184891   \n",
       "MXRA8           22.580011    True   0.845899     5.618146            7.386443   \n",
       "RPL22           82.435378    True  14.673621   568.010409            8.778378   \n",
       "ERRFI1          24.039442    True   1.665201    41.690070           24.395156   \n",
       "AL034417.2       6.224097    True   0.152080     0.776722            6.924184   \n",
       "...                   ...     ...        ...          ...                 ...   \n",
       "MT-ND4          93.221132    True  33.715851  2111.944134           17.854710   \n",
       "MT-ND5          85.202683    True  11.625198   221.280413            9.081979   \n",
       "MT-CYB          93.074253    True  42.056955  2675.267801           20.634519   \n",
       "AC233755.2       0.503316    True   0.153474    59.818648           28.106683   \n",
       "AC233755.1       1.349038    True   0.148759    12.703186           18.970033   \n",
       "\n",
       "            highly_variable_rank  highly_variable_features  \n",
       "ISG15                     1864.0                      True  \n",
       "MXRA8                     1808.0                      True  \n",
       "RPL22                     1461.0                      True  \n",
       "ERRFI1                     337.0                      True  \n",
       "AL034417.2                1950.0                      True  \n",
       "...                          ...                       ...  \n",
       "MT-ND4                     550.0                      True  \n",
       "MT-ND5                    1391.0                      True  \n",
       "MT-CYB                     425.0                      True  \n",
       "AC233755.2                 274.0                      True  \n",
       "AC233755.1                 497.0                      True  \n",
       "\n",
       "[2000 rows x 12 columns]"
      ]
     },
     "execution_count": 80,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "merged_adata=ov.pp.preprocess(merged_adata,mode='shiftlog|pearson',\n",
    "                       n_HVGs=2000)  # , batch_key='batch'\n",
    "merged_adata.raw = merged_adata\n",
    "merged_adata = merged_adata[:, merged_adata.var.highly_variable_features]\n",
    "merged_adata.var"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2adf6345-c1fb-4c16-9db2-3e74a1cdb448",
   "metadata": {},
   "source": [
    "## annotation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "75d10c9e-2b9e-480e-9490-cbeec092b6fa",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "from gseapy import Biomart\n",
    "\n",
    "query = Biomart().query(\n",
    "        dataset='hsapiens_gene_ensembl',\n",
    "        attributes=[\n",
    "            'ensembl_gene_id',          # Ensembl Gene ID\n",
    "            'external_gene_name'        # Gene Symbol\n",
    "        ]\n",
    "    )\n",
    "query.columns = ['Human_Gene_ID', 'Human_Gene_Symbol']\n",
    "ID2Symbol_dict = query.set_index('Human_Gene_ID')['Human_Gene_Symbol'].to_dict()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "id": "cce2cb13-2b38-4097-a4a0-590d728291b3",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "# merged_adata.var['gene_symbol'] = merged_adata.var['gene_ids'].map(ID2Symbol_dict)\n",
    "# merged_adata.var\n",
    "# adata.var['gene_ensembol'] = adata.var.index\n",
    "# adata.var.index = adata.var['gene_symbol'].astype(str).tolist()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "44433e8b-e3ef-4432-a53c-dfd5cdb0ef79",
   "metadata": {},
   "source": [
    "# 聚类"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "e1f89561-f331-47cb-8729-5c703eed2b52",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "AnnData object with n_obs × n_vars = 106891 × 2000\n",
       "    obs: 'n_genes', 'doublet_score', 'predicted_doublet', 'nUMIs', 'mito_perc', 'detected_genes', 'cell_complexity', 'passing_mt', 'passing_nUMIs', 'passing_ngenes', 'batch', 'sample_source'\n",
       "    var: 'gene_ids', 'feature_types', 'mt', 'gene_name', 'n_cells', 'percent_cells', 'robust', 'means', 'variances', 'residual_variances', 'highly_variable_rank', 'highly_variable_features'\n",
       "    uns: 'log1p', 'hvg', 'pca', 'scaled|original|pca_var_ratios', 'scaled|original|cum_sum_eigenvalues', 'counts|original|pca_var_ratios', 'counts|original|cum_sum_eigenvalues', 'neighbors', 'umap'\n",
       "    obsm: 'X_pca', 'scaled|original|X_pca', 'counts|original|X_pca', 'X_umap', 'X_umap_scaled', 'X_umap_counts'\n",
       "    varm: 'PCs', 'scaled|original|pca_loadings', 'counts|original|pca_loadings'\n",
       "    layers: 'counts', 'scaled'\n",
       "    obsp: 'distances', 'connectivities'"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "merged_adata"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "id": "aaf8bb2b-ec50-4c03-a5ba-709b2c12f937",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "ov.pp.scale(merged_adata,max_value=10)\n",
    "\n",
    "ov.pp.pca(merged_adata,layer='scaled',n_pcs=50)\n",
    "ov.pp.pca(merged_adata,layer='counts',n_pcs=50)\n",
    "\n",
    "sc.pp.neighbors(merged_adata, n_neighbors=15, n_pcs=50,\n",
    "               use_rep='scaled|original|X_pca')\n",
    "sc.tl.umap(merged_adata)\n",
    "#umap函数默认是存放在adata.obsm['X_umap']中的，我们将其存放在adata.obsm['X_umap_scaled']中来区分counts的结果\n",
    "merged_adata.obsm['X_umap_scaled']=merged_adata.obsm['X_umap']\n",
    "\n",
    "sc.pp.neighbors(merged_adata, n_neighbors=15, n_pcs=50,\n",
    "               use_rep='counts|original|X_pca')\n",
    "sc.tl.umap(merged_adata)\n",
    "merged_adata.obsm['X_umap_counts']=merged_adata.obsm['X_umap']\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 82,
   "id": "4369db6b-6a09-42b7-a886-d0fbfbdd0d44",
   "metadata": {},
   "outputs": [],
   "source": [
    "sc.tl.leiden(merged_adata, key_added=\"leiden_res0_25\", resolution=0.25)\n",
    "sc.tl.leiden(merged_adata, key_added=\"leiden_res0_5\", resolution=0.5)\n",
    "sc.tl.leiden(merged_adata, key_added=\"leiden_res1\", resolution=1.0)\n",
    "sc.tl.leiden(merged_adata, key_added=\"leiden_res1_5\", resolution=1.5)\n",
    "sc.tl.leiden(merged_adata, key_added=\"leiden_res2\", resolution=2.0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 83,
   "id": "d50b4e25-091d-49e4-844b-cb30cef2aa1c",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Jul 20 03:48:45 PM: Your dataset appears to contain duplicated items (rows); when embedding, you should typically have unique items.\n",
      "Jul 20 03:48:45 PM: The following items have duplicates [   52    54    55 ... 22638 22640 22641]\n"
     ]
    },
    {
     "ename": "ArpackError",
     "evalue": "ARPACK error -9: Starting vector is zero.",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mArpackError\u001b[0m                               Traceback (most recent call last)",
      "Input \u001b[0;32mIn [83]\u001b[0m, in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0m merged_adata\u001b[38;5;241m.\u001b[39mobsm[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mX_mde\u001b[39m\u001b[38;5;124m\"\u001b[39m] \u001b[38;5;241m=\u001b[39m \u001b[43mov\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mutils\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mmde\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmerged_adata\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mobsm\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mscaled|original|X_pca\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m      3\u001b[0m \u001b[38;5;66;03m# ov.utils.embedding(merged_adata,\u001b[39;00m\n\u001b[1;32m      4\u001b[0m \u001b[38;5;66;03m#                 basis='X_mde',\u001b[39;00m\n\u001b[1;32m      5\u001b[0m \u001b[38;5;66;03m#                 color=[\"leiden_res0_25\", \"leiden_res0_5\", \"leiden_res1\",\"leiden_res1_5\", \"leiden_res2\"],\u001b[39;00m\n\u001b[0;32m   (...)\u001b[0m\n\u001b[1;32m      8\u001b[0m \u001b[38;5;66;03m#                 ncols=2,\u001b[39;00m\n\u001b[1;32m      9\u001b[0m \u001b[38;5;66;03m#                 show=False,frameon='small',)\u001b[39;00m\n",
      "File \u001b[0;32m~/miniforge3/envs/singleGpu/lib/python3.12/site-packages/omicverse/utils/_mde.py:74\u001b[0m, in \u001b[0;36mmde\u001b[0;34m(data, device, **kwargs)\u001b[0m\n\u001b[1;32m     64\u001b[0m _kwargs \u001b[38;5;241m=\u001b[39m {\n\u001b[1;32m     65\u001b[0m     \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124membedding_dim\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;241m2\u001b[39m,\n\u001b[1;32m     66\u001b[0m     \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mconstraint\u001b[39m\u001b[38;5;124m\"\u001b[39m: pymde\u001b[38;5;241m.\u001b[39mStandardized(),\n\u001b[0;32m   (...)\u001b[0m\n\u001b[1;32m     70\u001b[0m     \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mn_neighbors\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;241m15\u001b[39m,\n\u001b[1;32m     71\u001b[0m }\n\u001b[1;32m     72\u001b[0m _kwargs\u001b[38;5;241m.\u001b[39mupdate(kwargs)\n\u001b[0;32m---> 74\u001b[0m emb \u001b[38;5;241m=\u001b[39m \u001b[43mpymde\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mpreserve_neighbors\u001b[49m\u001b[43m(\u001b[49m\u001b[43mdata\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43m_kwargs\u001b[49m\u001b[43m)\u001b[49m\u001b[38;5;241m.\u001b[39membed(verbose\u001b[38;5;241m=\u001b[39m_kwargs[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mverbose\u001b[39m\u001b[38;5;124m\"\u001b[39m])\n\u001b[1;32m     76\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(emb, torch\u001b[38;5;241m.\u001b[39mTensor):\n\u001b[1;32m     77\u001b[0m     emb \u001b[38;5;241m=\u001b[39m emb\u001b[38;5;241m.\u001b[39mcpu()\u001b[38;5;241m.\u001b[39mnumpy()\n",
      "File \u001b[0;32m~/miniforge3/envs/singleGpu/lib/python3.12/site-packages/pymde/recipes.py:367\u001b[0m, in \u001b[0;36mpreserve_neighbors\u001b[0;34m(data, embedding_dim, attractive_penalty, repulsive_penalty, constraint, n_neighbors, repulsive_fraction, max_distance, init, device, verbose)\u001b[0m\n\u001b[1;32m    365\u001b[0m \u001b[38;5;66;03m# use cg + torch when using GPU\u001b[39;00m\n\u001b[1;32m    366\u001b[0m cg \u001b[38;5;241m=\u001b[39m device \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcuda\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m--> 367\u001b[0m X_init \u001b[38;5;241m=\u001b[39m \u001b[43mquadratic\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mspectral\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m    368\u001b[0m \u001b[43m    \u001b[49m\u001b[43mn\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    369\u001b[0m \u001b[43m    \u001b[49m\u001b[43membedding_dim\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    370\u001b[0m \u001b[43m    \u001b[49m\u001b[43medges\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    371\u001b[0m \u001b[43m    \u001b[49m\u001b[43mweights\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    372\u001b[0m \u001b[43m    \u001b[49m\u001b[43mmax_iter\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;241;43m1000\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[1;32m    373\u001b[0m \u001b[43m    \u001b[49m\u001b[43mdevice\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mdevice\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    374\u001b[0m \u001b[43m    \u001b[49m\u001b[43mcg\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcg\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    375\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m    376\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(\n\u001b[1;32m    377\u001b[0m     constraint, (constraints\u001b[38;5;241m.\u001b[39m_Centered, constraints\u001b[38;5;241m.\u001b[39m_Standardized)\n\u001b[1;32m    378\u001b[0m ):\n\u001b[1;32m    379\u001b[0m     constraint\u001b[38;5;241m.\u001b[39mproject_onto_constraint(X_init, inplace\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m)\n",
      "File \u001b[0;32m~/miniforge3/envs/singleGpu/lib/python3.12/site-packages/pymde/quadratic.py:174\u001b[0m, in \u001b[0;36mspectral\u001b[0;34m(n_items, embedding_dim, edges, weights, cg, max_iter, device)\u001b[0m\n\u001b[1;32m    172\u001b[0m use_scipy \u001b[38;5;241m=\u001b[39m \u001b[38;5;129;01mnot\u001b[39;00m cg\n\u001b[1;32m    173\u001b[0m L \u001b[38;5;241m=\u001b[39m _laplacian(n_items, embedding_dim, edges, weights, use_scipy\u001b[38;5;241m=\u001b[39muse_scipy)\n\u001b[0;32m--> 174\u001b[0m emb \u001b[38;5;241m=\u001b[39m \u001b[43m_spectral\u001b[49m\u001b[43m(\u001b[49m\u001b[43mL\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43membedding_dim\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcg\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcg\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdevice\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mdevice\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmax_iter\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmax_iter\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m    175\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m use_scipy:\n\u001b[1;32m    176\u001b[0m     emb \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m=\u001b[39m emb\u001b[38;5;241m.\u001b[39mmean(axis\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m0\u001b[39m)\n",
      "File \u001b[0;32m~/miniforge3/envs/singleGpu/lib/python3.12/site-packages/pymde/quadratic.py:85\u001b[0m, in \u001b[0;36m_spectral\u001b[0;34m(L, m, cg, max_iter, edges, weights, warm_start, device)\u001b[0m\n\u001b[1;32m     83\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m cg:\n\u001b[1;32m     84\u001b[0m     num_lanczos_vectors \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mmax\u001b[39m(\u001b[38;5;241m2\u001b[39m \u001b[38;5;241m*\u001b[39m k \u001b[38;5;241m+\u001b[39m \u001b[38;5;241m1\u001b[39m, \u001b[38;5;28mint\u001b[39m(np\u001b[38;5;241m.\u001b[39msqrt(L\u001b[38;5;241m.\u001b[39mshape[\u001b[38;5;241m0\u001b[39m])))\n\u001b[0;32m---> 85\u001b[0m     eigenvalues, eigenvectors \u001b[38;5;241m=\u001b[39m \u001b[43mscipy\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msparse\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mlinalg\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43meigsh\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m     86\u001b[0m \u001b[43m        \u001b[49m\u001b[43mL\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m     87\u001b[0m \u001b[43m        \u001b[49m\u001b[43mk\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m     88\u001b[0m \u001b[43m        \u001b[49m\u001b[43mwhich\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mSM\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[1;32m     89\u001b[0m \u001b[43m        \u001b[49m\u001b[43mncv\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mnum_lanczos_vectors\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m     90\u001b[0m \u001b[43m        \u001b[49m\u001b[43mtol\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;241;43m1e-4\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[1;32m     91\u001b[0m \u001b[43m        \u001b[49m\u001b[43mv0\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mnp\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mones\u001b[49m\u001b[43m(\u001b[49m\u001b[43mL\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mshape\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m0\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m     92\u001b[0m \u001b[43m        \u001b[49m\u001b[43mmaxiter\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mL\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mshape\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m0\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;241;43m5\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[1;32m     93\u001b[0m \u001b[43m    \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m     94\u001b[0m     order \u001b[38;5;241m=\u001b[39m np\u001b[38;5;241m.\u001b[39margsort(eigenvalues)[\u001b[38;5;241m1\u001b[39m:k]\n\u001b[1;32m     95\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n",
      "File \u001b[0;32m~/miniforge3/envs/singleGpu/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/arpack/arpack.py:1696\u001b[0m, in \u001b[0;36meigsh\u001b[0;34m(A, k, M, sigma, which, v0, ncv, maxiter, tol, return_eigenvectors, Minv, OPinv, mode)\u001b[0m\n\u001b[1;32m   1694\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m _ARPACK_LOCK:\n\u001b[1;32m   1695\u001b[0m     \u001b[38;5;28;01mwhile\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m params\u001b[38;5;241m.\u001b[39mconverged:\n\u001b[0;32m-> 1696\u001b[0m         \u001b[43mparams\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43miterate\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m   1698\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m params\u001b[38;5;241m.\u001b[39mextract(return_eigenvectors)\n",
      "File \u001b[0;32m~/miniforge3/envs/singleGpu/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/arpack/arpack.py:578\u001b[0m, in \u001b[0;36m_SymmetricArpackParams.iterate\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m    576\u001b[0m     \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_raise_no_convergence()\n\u001b[1;32m    577\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m--> 578\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m ArpackError(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39minfo, infodict\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39miterate_infodict)\n",
      "\u001b[0;31mArpackError\u001b[0m: ARPACK error -9: Starting vector is zero."
     ]
    }
   ],
   "source": [
    "merged_adata.obsm[\"X_mde\"] = ov.utils.mde(merged_adata.obsm[\"scaled|original|X_pca\"])\n",
    "\n",
    "# ov.utils.embedding(merged_adata,\n",
    "#                 basis='X_mde',\n",
    "#                 color=[\"leiden_res0_25\", \"leiden_res0_5\", \"leiden_res1\",\"leiden_res1_5\", \"leiden_res2\"],\n",
    "#                 title=['Resolution:0.25','Resolution:0.5','Resolution:1','Resolution:1.5','Resolution:2'],\n",
    "#                 palette=ov.palette()[12:],\n",
    "#                 ncols=2,\n",
    "#                 show=False,frameon='small',)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "id": "b65862a2-9def-4a1d-b7d3-32cbe22038f1",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "重复细胞数量: 7160\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "pca_data = merged_adata.obsm[\"scaled|original|X_pca\"]\n",
    "unique_rows, counts = np.unique(pca_data, axis=0, return_counts=True)\n",
    "duplicate_cells = sum(counts > 1)\n",
    "print(f\"重复细胞数量: {duplicate_cells}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 89,
   "id": "0d2ddf89-b0ad-4003-a51b-8e2f6a6fa2fa",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "np.random.seed(42)  ## 移除重复新报\n",
    "for i in range(pca_data.shape[0]):\n",
    "    if np.any(np.all(pca_data[i] == pca_data[:i], axis=1)):\n",
    "        pca_data[i] += np.random.normal(0, 1e-5, size=pca_data.shape[1])\n",
    "merged_adata.obsm[\"scaled|original|X_pca\"] = pca_data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 90,
   "id": "af15cbb3-6f06-4f2c-bac1-7d9903994674",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "ename": "ArpackError",
     "evalue": "ARPACK error -9: Starting vector is zero.",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mArpackError\u001b[0m                               Traceback (most recent call last)",
      "Input \u001b[0;32mIn [90]\u001b[0m, in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0m merged_adata\u001b[38;5;241m.\u001b[39mobsm[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mX_mde\u001b[39m\u001b[38;5;124m\"\u001b[39m] \u001b[38;5;241m=\u001b[39m \u001b[43mov\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mutils\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mmde\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmerged_adata\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mobsm\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mscaled|original|X_pca\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m)\u001b[49m\n",
      "File \u001b[0;32m~/miniforge3/envs/singleGpu/lib/python3.12/site-packages/omicverse/utils/_mde.py:74\u001b[0m, in \u001b[0;36mmde\u001b[0;34m(data, device, **kwargs)\u001b[0m\n\u001b[1;32m     64\u001b[0m _kwargs \u001b[38;5;241m=\u001b[39m {\n\u001b[1;32m     65\u001b[0m     \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124membedding_dim\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;241m2\u001b[39m,\n\u001b[1;32m     66\u001b[0m     \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mconstraint\u001b[39m\u001b[38;5;124m\"\u001b[39m: pymde\u001b[38;5;241m.\u001b[39mStandardized(),\n\u001b[0;32m   (...)\u001b[0m\n\u001b[1;32m     70\u001b[0m     \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mn_neighbors\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;241m15\u001b[39m,\n\u001b[1;32m     71\u001b[0m }\n\u001b[1;32m     72\u001b[0m _kwargs\u001b[38;5;241m.\u001b[39mupdate(kwargs)\n\u001b[0;32m---> 74\u001b[0m emb \u001b[38;5;241m=\u001b[39m \u001b[43mpymde\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mpreserve_neighbors\u001b[49m\u001b[43m(\u001b[49m\u001b[43mdata\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43m_kwargs\u001b[49m\u001b[43m)\u001b[49m\u001b[38;5;241m.\u001b[39membed(verbose\u001b[38;5;241m=\u001b[39m_kwargs[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mverbose\u001b[39m\u001b[38;5;124m\"\u001b[39m])\n\u001b[1;32m     76\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(emb, torch\u001b[38;5;241m.\u001b[39mTensor):\n\u001b[1;32m     77\u001b[0m     emb \u001b[38;5;241m=\u001b[39m emb\u001b[38;5;241m.\u001b[39mcpu()\u001b[38;5;241m.\u001b[39mnumpy()\n",
      "File \u001b[0;32m~/miniforge3/envs/singleGpu/lib/python3.12/site-packages/pymde/recipes.py:367\u001b[0m, in \u001b[0;36mpreserve_neighbors\u001b[0;34m(data, embedding_dim, attractive_penalty, repulsive_penalty, constraint, n_neighbors, repulsive_fraction, max_distance, init, device, verbose)\u001b[0m\n\u001b[1;32m    365\u001b[0m \u001b[38;5;66;03m# use cg + torch when using GPU\u001b[39;00m\n\u001b[1;32m    366\u001b[0m cg \u001b[38;5;241m=\u001b[39m device \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcuda\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m--> 367\u001b[0m X_init \u001b[38;5;241m=\u001b[39m \u001b[43mquadratic\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mspectral\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m    368\u001b[0m \u001b[43m    \u001b[49m\u001b[43mn\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    369\u001b[0m \u001b[43m    \u001b[49m\u001b[43membedding_dim\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    370\u001b[0m \u001b[43m    \u001b[49m\u001b[43medges\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    371\u001b[0m \u001b[43m    \u001b[49m\u001b[43mweights\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    372\u001b[0m \u001b[43m    \u001b[49m\u001b[43mmax_iter\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;241;43m1000\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[1;32m    373\u001b[0m \u001b[43m    \u001b[49m\u001b[43mdevice\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mdevice\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    374\u001b[0m \u001b[43m    \u001b[49m\u001b[43mcg\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcg\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    375\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m    376\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(\n\u001b[1;32m    377\u001b[0m     constraint, (constraints\u001b[38;5;241m.\u001b[39m_Centered, constraints\u001b[38;5;241m.\u001b[39m_Standardized)\n\u001b[1;32m    378\u001b[0m ):\n\u001b[1;32m    379\u001b[0m     constraint\u001b[38;5;241m.\u001b[39mproject_onto_constraint(X_init, inplace\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m)\n",
      "File \u001b[0;32m~/miniforge3/envs/singleGpu/lib/python3.12/site-packages/pymde/quadratic.py:174\u001b[0m, in \u001b[0;36mspectral\u001b[0;34m(n_items, embedding_dim, edges, weights, cg, max_iter, device)\u001b[0m\n\u001b[1;32m    172\u001b[0m use_scipy \u001b[38;5;241m=\u001b[39m \u001b[38;5;129;01mnot\u001b[39;00m cg\n\u001b[1;32m    173\u001b[0m L \u001b[38;5;241m=\u001b[39m _laplacian(n_items, embedding_dim, edges, weights, use_scipy\u001b[38;5;241m=\u001b[39muse_scipy)\n\u001b[0;32m--> 174\u001b[0m emb \u001b[38;5;241m=\u001b[39m \u001b[43m_spectral\u001b[49m\u001b[43m(\u001b[49m\u001b[43mL\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43membedding_dim\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcg\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcg\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdevice\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mdevice\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmax_iter\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmax_iter\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m    175\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m use_scipy:\n\u001b[1;32m    176\u001b[0m     emb \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m=\u001b[39m emb\u001b[38;5;241m.\u001b[39mmean(axis\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m0\u001b[39m)\n",
      "File \u001b[0;32m~/miniforge3/envs/singleGpu/lib/python3.12/site-packages/pymde/quadratic.py:85\u001b[0m, in \u001b[0;36m_spectral\u001b[0;34m(L, m, cg, max_iter, edges, weights, warm_start, device)\u001b[0m\n\u001b[1;32m     83\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m cg:\n\u001b[1;32m     84\u001b[0m     num_lanczos_vectors \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mmax\u001b[39m(\u001b[38;5;241m2\u001b[39m \u001b[38;5;241m*\u001b[39m k \u001b[38;5;241m+\u001b[39m \u001b[38;5;241m1\u001b[39m, \u001b[38;5;28mint\u001b[39m(np\u001b[38;5;241m.\u001b[39msqrt(L\u001b[38;5;241m.\u001b[39mshape[\u001b[38;5;241m0\u001b[39m])))\n\u001b[0;32m---> 85\u001b[0m     eigenvalues, eigenvectors \u001b[38;5;241m=\u001b[39m \u001b[43mscipy\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msparse\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mlinalg\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43meigsh\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m     86\u001b[0m \u001b[43m        \u001b[49m\u001b[43mL\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m     87\u001b[0m \u001b[43m        \u001b[49m\u001b[43mk\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m     88\u001b[0m \u001b[43m        \u001b[49m\u001b[43mwhich\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mSM\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[1;32m     89\u001b[0m \u001b[43m        \u001b[49m\u001b[43mncv\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mnum_lanczos_vectors\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m     90\u001b[0m \u001b[43m        \u001b[49m\u001b[43mtol\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;241;43m1e-4\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[1;32m     91\u001b[0m \u001b[43m        \u001b[49m\u001b[43mv0\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mnp\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mones\u001b[49m\u001b[43m(\u001b[49m\u001b[43mL\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mshape\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m0\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m     92\u001b[0m \u001b[43m        \u001b[49m\u001b[43mmaxiter\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mL\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mshape\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m0\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;241;43m5\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[1;32m     93\u001b[0m \u001b[43m    \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m     94\u001b[0m     order \u001b[38;5;241m=\u001b[39m np\u001b[38;5;241m.\u001b[39margsort(eigenvalues)[\u001b[38;5;241m1\u001b[39m:k]\n\u001b[1;32m     95\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n",
      "File \u001b[0;32m~/miniforge3/envs/singleGpu/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/arpack/arpack.py:1696\u001b[0m, in \u001b[0;36meigsh\u001b[0;34m(A, k, M, sigma, which, v0, ncv, maxiter, tol, return_eigenvectors, Minv, OPinv, mode)\u001b[0m\n\u001b[1;32m   1694\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m _ARPACK_LOCK:\n\u001b[1;32m   1695\u001b[0m     \u001b[38;5;28;01mwhile\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m params\u001b[38;5;241m.\u001b[39mconverged:\n\u001b[0;32m-> 1696\u001b[0m         \u001b[43mparams\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43miterate\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m   1698\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m params\u001b[38;5;241m.\u001b[39mextract(return_eigenvectors)\n",
      "File \u001b[0;32m~/miniforge3/envs/singleGpu/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/arpack/arpack.py:578\u001b[0m, in \u001b[0;36m_SymmetricArpackParams.iterate\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m    576\u001b[0m     \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_raise_no_convergence()\n\u001b[1;32m    577\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m--> 578\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m ArpackError(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39minfo, infodict\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39miterate_infodict)\n",
      "\u001b[0;31mArpackError\u001b[0m: ARPACK error -9: Starting vector is zero."
     ]
    }
   ],
   "source": [
    "merged_adata.obsm[\"X_mde\"] = ov.utils.mde(merged_adata.obsm[\"scaled|original|X_pca\"])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "60740378-8ef8-4c23-8369-910e1fc9b531",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "merged_adata.obsm[\"scaled|original|X_pca\"].shape"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b7898725-d21d-4691-b3a1-25f839b46d51",
   "metadata": {},
   "source": [
    "## other"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "id": "53366223-f2a4-4af5-b4c9-534e7e9668ab",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Shape: (106891, 50)\n",
      "All zero? False\n",
      "Any NaN? False\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "X = merged_adata.obsm[\"scaled|original|X_pca\"]\n",
    "print(\"Shape:\", X.shape)\n",
    "print(\"All zero?\", np.all(X == 0))\n",
    "print(\"Any NaN?\", np.isnan(X).any())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "34b9490d-c9a1-417f-905a-fafe1bb1bb30",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "import scipy\n",
    "print(scipy.__version__)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a4f39dfa-894d-4a9f-8726-0429d32ef50c",
   "metadata": {},
   "outputs": [],
   "source": [
    "pip install scipy==1.14 -y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 84,
   "id": "f4926b22-d0a1-4b00-b0f3-ffc549ae8887",
   "metadata": {},
   "outputs": [],
   "source": [
    "import scanpy as sc\n",
    "\n",
    "merged_adata.write(\"full_analysis.h5ad\", compression=\"gzip\")\n",
    "\n",
    "# 读取并验证\n",
    "merged_adata = sc.read(\"full_analysis.h5ad\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 99,
   "id": "c9409f16-5f84-4b6e-b1a1-44aa70565ba0",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3.12.9 | packaged by conda-forge | (main, Mar  4 2025, 22:48:41) [GCC 13.3.0]\n",
      "sys.version_info(major=3, minor=12, micro=9, releaselevel='final', serial=0)\n"
     ]
    }
   ],
   "source": [
    "import sys\n",
    "print(sys.version)      # 输出详细版本及编译信息\n",
    "print(sys.version_info) # 结构化版本信息（元组）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 96,
   "id": "a1066f1d-43e3-4cbb-8177-23e3c1e16052",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "当前 Python 解释器路径: /lustre/home/acct-medfzx/medfzx-lkw/miniforge3/envs/singleGpu/bin/python\n"
     ]
    }
   ],
   "source": [
    "import sys\n",
    "print(\"当前 Python 解释器路径:\", sys.executable)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "sc_bone_1.14scipy",
   "language": "python",
   "name": "sc_bone"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
